#include "window/window_glfw.h"

#include "opengl/opengl_shader.h"
#include "render/scene2D.h"
#include "render/scene3D.h"

#include "imgui.h"
#include "backends/imgui_impl_glfw.h"
#include "backends/imgui_impl_opengl3.h"
namespace engine
{
    void framebuffer_size_callback(GLFWwindow *window, int width, int height);
    void processInput(GLFWwindow *window);

    GlfwWindow::GlfwWindow(string t)
    {
        this->init();
        this->setTitle(t);

        uiManager = std::make_shared<UIManager>();
    }

    GlfwWindow::GlfwWindow(string t, int x, int y, int width, int height)
    {
        this->init();
        this->setTitle(t);
        this->setPostion(x, y);
        this->setSize(width, height);

        uiManager = std::make_shared<UIManager>();
    }

    bool GlfwWindow::create()
    {
        if (!glfwInit())
        {
            ENGINE_ERROR("glfwInit Failed");
            return false;
        }
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

        // glfw window creation
        this->m_pGLFWwindow = glfwCreateWindow(this->width, this->height, this->title.c_str(), NULL, NULL);
        if (this->m_pGLFWwindow == NULL)
        {
            ENGINE_ERROR("Failed to create GLFW window");
            glfwTerminate();
            return false;
        }
        this->isCreated = true;
        glfwMakeContextCurrent(this->m_pGLFWwindow);

        // glfwSetKeyCallback(this->m_pGLFWwindow, keyCallback);
        // glfwSetCursorPosCallback(this->m_pGLFWwindow, cursorPositionCallback);
        // glfwSetMouseButtonCallback(this->m_pGLFWwindow, mouseButtonCallback);
        // glfwSetScrollCallback(this->m_pGLFWwindow, scrollCallback);
        glfwSetFramebufferSizeCallback(this->m_pGLFWwindow, framebuffer_size_callback);

        // glad: load all OpenGL function pointers
        if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
        {
            ENGINE_ERROR("Failed to initialize GLAD");
            return false;
        }

        uiManager->init(m_pGLFWwindow);

        // 初始化场景
        // this->m_pRenderSystem = new RenderSystem();
        // this->m_pScene = new Scene2D();
        // scene2D = new Scene2D();
        // scene3D = new Scene3D();
        ENGINE_INFO("Window Create Success");
        return true;
    }

    bool GlfwWindow::destory()
    {
        // glfw: terminate, clearing all previously allocated GLFW resources.
        // ------------------------------------------------------------------
        glfwTerminate();
        ENGINE_INFO("window destory");
        return true;
    }

    void GlfwWindow::loop()
    {
        while (!glfwWindowShouldClose(this->m_pGLFWwindow))
        {
            pre_render();
            render();
            post_render();
        }
    }

    // 窗口尺寸变化
    void framebuffer_size_callback(GLFWwindow *window, int width, int height)
    {
        // make sure the viewport matches the new window dimensions; note that width and
        // height will be significantly larger than specified on retina displays.
        glViewport(0, 0, width, height);
    }

    void GlfwWindow::pre_render()
    {
        glViewport(0, 0, width, height);
        glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // glEnable(GL_BLEND);
        // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    void GlfwWindow::render()
    {
        // this->m_pRenderSystem->processInput(this->m_pGLFWwindow);
        // if (this->m_pRenderSystem != NULL)
        // {
        //     // this->m_pRenderSystem->update();
        //     this->m_pRenderSystem->render(glfwGetTime());
        // }

        // if (scene2D != NULL)
        // {
        //     scene2D->processInput(this->m_pGLFWwindow);
        //     // this->m_pScene->update();
        //     scene2D->render(glfwGetTime());
        // }

        // if (scene3D != NULL)
        // {
        //     scene3D->processInput(this->m_pGLFWwindow);
        //     // this->m_pScene->update();
        //     scene3D->render(glfwGetTime());
        // }

        // Object3D *root = scene3D->objectRoot;

        // Entity3D *cube1 = (Entity3D *)root->getChildrenByName("cube1");

        uiManager->render();
    }

    void GlfwWindow::post_render()
    {
        glfwPollEvents();
        glfwSwapBuffers(m_pGLFWwindow);
    }

}